/*
 ------------------------------------------------------------------------------
 Copyright (C) 2009-2011 Eternal Games.

 This file is part of the Eternal Tech source code.

 The Eternal Tech source code is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or (at your
 option) any later version.

 The Eternal Tech source code is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 more details.

 You should have received a copy of the GNU General Public License along with
 the Eternal Tech source code; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 ------------------------------------------------------------------------------
*/


//
// cl_main.cpp - Initializes the client
//


#include "cl_local.h"
#include "client.h"


//clientActive_t				cl;
clientStatic_t				cls;

cvar_t						*cl_hand;

cvar_t						*cl_showPredictionMiss;

cvar_t						*cl_smallFont;
cvar_t						*cl_largeFont;

cvar_t						*cl_crosshairSize;
cvar_t						*cl_crosshairX;
cvar_t						*cl_crosshairY;
cvar_t						*cl_crosshairColor;
cvar_t						*cl_crosshairAlpha;

cvar_t						*cl_drawLogo;
cvar_t						*cl_drawCrosshair;
cvar_t						*cl_crosshairNames;
cvar_t						*cl_drawFPS;
cvar_t						*cl_showMaterial;

cvar_t						*cl_predict;


/*
 ==================
 CL_MapLoading
 ==================
*/
void CL_MapLoading ()
{
	if (cls.state == CS_UNINITIALIZED)
		return;

	// If we're already connected to the local server, stay connected
	if (cls.state >= CS_CONNECTED && NET_IsLocalAddress(cls.serverAddress))
	{
		cls.state = CS_CONNECTED;

		// Draw the loading screen
		CL_Loading();
		CL_UpdateScreen();

		return;
	}

	// Disconnect from server
	CL_Disconnect();

	// Connect to the local server
	Str_Copy(cls.serverName, "localhost", sizeof(cls.serverName));
	Str_Copy(cls.serverMessage, "", sizeof(cls.serverMessage));

	NET_StringToAdr(cls.serverName, &cls.serverAddress);

	// CL_CheckForResend will fire immediately
	cls.state = CS_CHALLENGING;		// We don't need a challenge on the localhost
	cls.connectTime = -99999;
	cls.connectCount = 0;

	// Draw the loading screen
	CL_Loading();
	CL_UpdateScreen();
}


/*
 ==============================================================================

    SCREEN UPDATE

 ==============================================================================
*/


/*
 ==================
 CL_UpdateScreen
 ==================
*/
void CL_UpdateScreen ()
{
	// Begin the frame
	R_BeginFrame();

	// Handle the connection state
	switch (cls.state){
	case CS_DISCONNECTED:
		break;
	case CS_CONNECTING:
	case CS_CHALLENGING:
	case CS_CONNECTED:
	case CS_LOADING:
	case CS_PRIMED:
		// Draw the loading screen and connection information
		CL_DrawLoading();
		break;
	case CS_ACTIVE:
		CL_RenderActiveFrame();
		break;
	}

	// The console will be drawn on top of everything
	Con_Draw();

	// End the frame
	R_EndFrame();
}


/*
 ==============================================================================

    RESTART FUNCTION

 ==============================================================================
*/


/*
 ==================
 CL_FullRestart
 ==================
*/
static void CL_FullRestart ()
{
	// Restart the sound system and renderer 
	S_Shutdown(true);
	R_Shutdown(true);

	R_Init(true);
	S_Init(true);

	// Load local media assets
	CL_LoadLocalMedia();

	// Load game media assets
	CL_LoadGameMedia();
}


/*
 ==============================================================================

    CONSOLE COMMANDS

 ==============================================================================
*/


/*
 ==================
 CL_RestartVideo_f
 ==================
*/
void CL_RestartVideo_f ()
{
	// If we are in the game, perform a full restart
	if (cls.state >= CS_PRIMED)
	{
		CL_FullRestart();
		return;
	}

	// Restart the renderer
	R_Shutdown(true);
	R_Init(true);

	// Load local media assets
	CL_LoadLocalMedia();
}

/*
 ==================
 CL_RestartSound_f
 ==================
*/
void CL_RestartSound_f ()
{
	// If we are in the game, perform a full restart
	if (cls.state >= CS_PRIMED)
	{
		CL_FullRestart();
		return;
	}

	// Restart the sound system
	S_Shutdown(true);
	S_Init(true);

	// Load local media assets
	CL_LoadLocalMedia();
}


/*
 ==============================================================================

    INITIALIZATION AND SHUTDOWN

 ==============================================================================
*/


/*
 ==================
 CL_Init
 ==================
*/
void CL_Init ()
{
	if (com_dedicated->integerValue)
		return;   // Nothing running on the client

	if (cls.state != CS_UNINITIALIZED)
		return;   // Already running

	Com_Printf("-------- Client Initialization --------\n");

	cls.state = CS_DISCONNECTED;

	// Register variables
	cl_hand = CVar_Register("cl_hand", "0", CVAR_INTEGER, CVAR_USERINFO | CVAR_ARCHIVE, "Sets which side of the screen the hands should be on (1 = left, 2 = center, 3 = right)", 0, 3);

	cl_showPredictionMiss = CVar_Register("cl_showPredictionMiss", "0", CVAR_BOOL, 0, "Report prediction misses", 0, 0);

	cl_smallFont = CVar_Register("cl_smallFont", "0.2", CVAR_FLOAT, CVAR_ARCHIVE, "Small font threshold", 0.0f, 1.0f);
	cl_largeFont = CVar_Register("cl_largeFont", "0.4", CVAR_FLOAT, CVAR_ARCHIVE, "Large font threshold", 0.0f, 1.0f);

	cl_crosshairSize = CVar_Register("cl_crosshairSize", "24", CVAR_INTEGER, CVAR_ARCHIVE, "Crosshair size", 0, 0); // TODO: mins and max
	cl_crosshairX = CVar_Register("cl_crosshairX", "0", CVAR_INTEGER, CVAR_ARCHIVE, "Crosshair X offset", 0, 0); // TODO: mins and max
	cl_crosshairY = CVar_Register("cl_crosshairY", "0", CVAR_INTEGER, CVAR_ARCHIVE, "Crosshair Y offset", 0, 0); // TODO: mins and max
	cl_crosshairColor = CVar_Register("cl_crosshairColor", "7", CVAR_INTEGER, CVAR_ARCHIVE, "Crosshair color index", 0, 0); // TODO: mins and max
	cl_crosshairAlpha = CVar_Register("cl_crosshairAlpha", "1.0", CVAR_FLOAT, CVAR_ARCHIVE, "Crosshair translucency level", 0.0f, 1.0f);

	cl_drawLogo = CVar_Register("cl_drawLogo", "0", CVAR_BOOL, CVAR_ARCHIVE | CVAR_GAME, "Draw the game logo", 0, 0);
	cl_drawCrosshair = CVar_Register("cl_drawCrosshair", "0", CVAR_INTEGER, CVAR_ARCHIVE, "Draw a crosshair", 0, 20);
	cl_crosshairNames = CVar_Register("cl_crosshairNames", "1", CVAR_BOOL, CVAR_ARCHIVE, "Draw player names under crosshair", 0, 0);
	cl_drawFPS = CVar_Register("cl_drawFPS", "0", CVAR_BOOL, CVAR_ARCHIVE | CVAR_GAME, "Draw frames rendered per second", 0, 0);
	cl_showMaterial = CVar_Register("cl_showMaterial", "0", CVAR_BOOL, CVAR_CHEAT, "Show material name, flags, and contents under crosshair", 0, 0);
	
	cl_predict = CVar_Register("cl_predict", "1", CVAR_BOOL, CVAR_ARCHIVE, "Predict player movement", 0, 0);

	// Add commands
	Cmd_AddCommand("restartVideo", CL_RestartVideo_f);
	Cmd_AddCommand("restartSound", CL_RestartSound_f);
	Cmd_AddCommand("listParticles", CL_ListParticles_f);
	Cmd_AddCommand("testModel", CL_TestModel_f);
	Cmd_AddCommand("testDecal", CL_TestDecal_f);

	S_Init(true);

	CL_InitParticles();

	Com_Printf("---------------------------------------\n");
}

/*
 ==================
 CL_Shutdown
 ==================
*/
void CL_Shutdown ()
{
	if (cls.state == CS_UNINITIALIZED)
		return;   // Nothing running on the client

	Com_Printf("-------- Client Shutdown --------\n");

	// Remove commands
	Cmd_RemoveCommand("restartVideo");
	Cmd_RemoveCommand("restartSound");
	Cmd_RemoveCommand("listParticles");
	Cmd_RemoveCommand("testModel");
	Cmd_RemoveCommand("testDecal");

	CL_ShutdownParticles();

	S_Shutdown(true);

	Com_Printf("---------------------------------\n");
}